<template>
    <div class="trant">
        <!-- 左边表格数据 -->
        <div class="trant-left">
            <p>未选中</p>
            <div class="trant-content">
                <div class="content-input">
                    <el-input
                        :placeholder="leftPlaceholder"
                        v-model="searchData.left.temp"
                        style="width:280px"
                        size="mini"
                        @keyup.enter.native="onSearch('left')"
                    ></el-input>
                    <el-button class="left-p" type="primary" icon="el-icon-search" @click="onSearch('left')"> </el-button>
                </div>
                <div>
                    <el-table
                        ref="leftTable"
                        :data="filterLeftTableData"
                        tooltip-effect="dark"
                        style="width: 100%"
                        height="300px"
                        :row-key="indexKey"
                        border
                        @select-all="selectionChange('left')"
                        @select="selectionChange('left')"
                    >
                        <el-table-column
                            type="selection"
                            width="40"
                            align="center"
                            :reserve-selection="true"
                            :selectable="getDisabled"
                        ></el-table-column>
                        <template v-for="col in leftColumnsCache">
                            <el-table-column
                                :key="col.prop"
                                :prop="col.prop"
                                :label="col.label"
                                :width="col.width"
                                show-overflow-tooltip
                            ></el-table-column>
                        </template>
                    </el-table>
                </div>
                <el-pagination
                    layout="total, prev, pager, next"
                    :total="filterLeftTableAllData.length"
                    :page-size="page.left.pageSize"
                    :current-page.sync="page.left.currentPage"
                    :pager-count="5"
                    background
                ></el-pagination>
            </div>
        </div>

        <!-- 中间2个键 -->
        <div class="trant-but">
            <el-button
                type="primary"
                icon="el-icon-d-arrow-right"
                :disabled="!leftTableDataStorage.length || !!this.isDisabled"
                @click="moveAllSelections('left', 'right')"
            ></el-button>
            <br />
            <el-button
                type="primary"
                icon="el-icon-arrow-right"
                :disabled="!leftTableDataStorage.length || !!this.isDisabled || !selections.left.length"
                @click="moveSelections('left', 'right')"
            ></el-button>
            <br />
            <el-button
                type="primary"
                icon="el-icon-arrow-left"
                :disabled="!rightTableDataStorage.length || !!this.isDisabled || !selections.right.length"
                @click="moveSelections('right', 'left')"
            ></el-button>
            <br />
            <el-button
                type="primary"
                icon="el-icon-d-arrow-left"
                :disabled="!rightTableDataStorage.length || !!this.isDisabled"
                @click="moveAllSelections('right', 'left')"
            ></el-button>
        </div>
        <!-- 右边表格数据 -->
        <div class="trant-right">
            <p>已选中</p>
            <div class="trant-content">
                <div class="content-input">
                    <el-input
                        :placeholder="rightPlaceholder || leftPlaceholder"
                        v-model="searchData.right.temp"
                        style="width:280px"
                        size="mini"
                        @keyup.enter.native="onSearch('right')"
                    ></el-input>
                    <el-button class="left-p" type="primary" icon="el-icon-search" @click="onSearch('right')"> </el-button>
                </div>
                <div>
                    <el-table
                        ref="rightTable"
                        :data="filterRightTableData"
                        tooltip-effect="dark"
                        style="width: 100%"
                        :row-key="indexKey"
                        height="300px"
                        border
                        @select-all="selectionChange('right')"
                        @select="selectionChange('right')"
                    >
                        <el-table-column
                            type="selection"
                            width="40"
                            align="center"
                            :reserve-selection="true"
                            :selectable="getSelectable"
                        ></el-table-column>
                        <template v-for="col in leftColumnsCache">
                            <el-table-column
                                :key="col.prop"
                                :prop="col.prop"
                                :label="col.label"
                                :width="col.width"
                                show-overflow-tooltip
                            ></el-table-column>
                        </template>
                    </el-table>
                </div>
                <el-pagination
                    layout="total, prev, pager, next"
                    :total="filterRightTableAllData.length"
                    :page-size="page.right.pageSize"
                    :current-page.sync="page.right.currentPage"
                    :pager-count="5"
                    background
                ></el-pagination>
            </div>
        </div>
    </div>
</template>
<script lang="ts">
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
import { getCurrentPageData } from '@/utils/tools';

@Component({
    name: 'RiskTrantable',
})
export default class RiskTrantable extends Vue {
    // 主键
    @Prop() indexKey: string;
    // 左边、右边表格数据
    @Prop() leftTableData!: any[];
    @Prop() rightTableData!: any[];
    // 左边、右边表格数据格式
    @Prop() leftColumns: any[];
    @Prop() rightColumns?: any[];
    // 搜索输入框提示
    @Prop({ default: '请输入' }) leftPlaceholder?: string;
    @Prop() rightPlaceholder?: string;
    // 搜索的参数
    @Prop() leftSearchNames?: string[];
    @Prop() rightSearchNames?: string[];
    // 排序规则
    @Prop({ default: '' }) sort?: string | ((a: any, b: any) => number);
    @Prop({ default: false }) isDisabled: boolean;

    // 组件内部维护的数据
    private leftTableDataStorage: any[] = [];
    private rightTableDataStorage: any[] = [];
    private leftColumnsCache = [];
    // 搜索条件
    private searchData = {
        left: {
            data: '',
            temp: '',
        },
        right: {
            data: '',
            temp: '',
        },
    };
    // 分页
    private page = {
        left: {
            currentPage: 1,
            pageSize: 25,
        },
        right: {
            currentPage: 1,
            pageSize: 25,
        },
    };

    /**
     * 过滤获取左侧全部数据(不分页)
     */
    get filterLeftTableAllData() {
        let data = this.leftTableDataStorage;
        let searchNames = this.leftSearchNames;
        // 匹配搜索功能
        if (searchNames && searchNames.length) {
            data = data.filter(item => {
                for (let i = 0; i < searchNames.length; i++) {
                    let key = searchNames[i];
                    let itemStr = item[key] ? String(item[key]) : '';
                    if (itemStr.indexOf(this.searchData.left.data) > -1) {
                        return true;
                    }
                }
                return false;
            });
        }
        return data;
    }
    /**
     * 过滤获取左侧当前页数据
     */
    get filterLeftTableData() {
        let data = this.leftTableDataStorage;
        let searchNames = this.leftSearchNames;
        // 匹配搜索功能
        if (searchNames && searchNames.length) {
            data = data.filter(item => {
                for (let i = 0; i < searchNames.length; i++) {
                    let key = searchNames[i];
                    let itemStr = item[key] ? String(item[key]) : '';
                    if (itemStr.indexOf(this.searchData.left.data) > -1) {
                        return true;
                    }
                }
                return false;
            });
        }
        return getCurrentPageData(data, this.page.left.currentPage, this.page.left.pageSize);
    }
    /**
     * 过滤获取右侧全部数据(不分页)
     */
    get filterRightTableAllData() {
        let data = this.rightTableDataStorage;
        let searchName = this.rightSearchNames ? this.rightSearchNames : this.leftSearchNames;
        // 匹配搜索功能
        if (searchName && searchName.length) {
            data = data.filter(item => {
                for (let i = 0; i < searchName.length; i++) {
                    let key = searchName[i];
                    let itemStr = item[key] ? String(item[key]) : '';
                    if (itemStr.indexOf(this.searchData.right.data) > -1) {
                        return true;
                    }
                }
                return false;
            });
        }
        return data;
    }
    /**
     * 过滤获取右侧当前页数据
     */
    get filterRightTableData() {
        let data = this.rightTableDataStorage;
        let searchName = this.rightSearchNames ? this.rightSearchNames : this.leftSearchNames;
        // 匹配搜索功能
        if (searchName && searchName.length) {
            data = data.filter(item => {
                for (let i = 0; i < searchName.length; i++) {
                    let key = searchName[i];
                    let itemStr = item[key] ? String(item[key]) : '';
                    if (itemStr.indexOf(this.searchData.right.data) > -1) {
                        return true;
                    }
                }
                return false;
            });
        }
        return getCurrentPageData(data, this.page.right.currentPage, this.page.right.pageSize);
    }

    /**
     * 监听两组表格数据
     */
    @Watch('leftTableData', { immediate: true, deep: true })
    watchLeftTableData() {
        let temp: any[] = JSON.parse(JSON.stringify(this.leftTableData));
        this.sortData(temp);
        temp = temp.map(item => {
            let result: any = {};
            this.leftColumns.forEach(props => {
                let name: string = props.prop;
                result[name] = item[name];
            });
            result.isDisabled = item.isDisabled ? item.isDisabled : false;
            return result;
        });
        // temp = this.duplicateRemoval(temp, this.rightTableData);
        this.leftTableDataStorage = temp;
        this.initData();
    }
    @Watch('rightTableData', { immediate: true, deep: true })
    watchRightTableData() {
        let temp: any[] = JSON.parse(JSON.stringify(this.rightTableData));
        this.sortData(temp);
        temp = temp.map(item => {
            let result: any = {};
            this.leftColumns.forEach(props => {
                let name: string = props.prop;
                result[name] = item[name];
            });
            result.isDisabled = item.isDisabled ? item.isDisabled : false;
            return result;
        });
        this.rightTableDataStorage = temp;
        this.initData();
    }
    @Watch('leftColumns', { immediate: true, deep: true })
    watchLeftColumns(value) {
        this.leftColumnsCache = value
            .filter(item => {
                return !item.hidden;
            })
            .map(item => {
                return {
                    label: item.label,
                    prop: item.prop,
                    width: item.width ? item.width : null,
                    hidden: !!item.hidden,
                };
            });
    }
    /**
     * 搜索功能
     */
    onSearch(type: string): void {
        this.page[type].currentPage = 1;
        this.searchData[type].data = this.searchData[type].temp;
    }

    // // 过滤数据，右边有的数据，左边过滤掉
    // duplicateRemoval(leftData, rightData) {
    //     let left = [];
    //     left = leftData.filter(leftItem => {
    //         let leftKey = leftItem[this.indexKey];
    //         return !rightData.some(item => item[this.indexKey] === leftKey);
    //     });
    //     return left;
    // }

    /**
     * 移动表格选中数据
     * @param from 数据来源
     * @param to   数据最终要调价的地方
     */
    moveSelections(from: string, to: string) {
        const selections: any[] = (this.$refs[from + 'Table'] as any).selection;
        const fromTableData: any[] = this[from + 'TableDataStorage'];
        const toTableData: any[] = this[to + 'TableDataStorage'];

        // 新的来源数据
        const fromData = fromTableData.filter(item => {
            return !selections.includes(item);
        });
        // 需要移动的数据
        const moveData = fromTableData.filter(item => {
            return selections.includes(item);
        });
        const toData = toTableData.concat(moveData);

        // 排序
        this.sortData(fromData);
        this.sortData(toData);

        this[from + 'TableDataStorage'] = fromData;
        this[to + 'TableDataStorage'] = toData;

        // 清除选中项
        (this.$refs[from + 'Table'] as any).clearSelection();
        (this.$refs[to + 'Table'] as any).clearSelection();
        this.selections[from] = [];
        this.selections[to] = [];
    }
    selections: any = {
        left: [],
        right: [],
    };
    /**
     * 勾选变化
     * @param from 处理方向
     */
    selectionChange(from: any) {
        this.selections[from] = (this.$refs[from + 'Table'] as any).selection;
    }

    /**
     * 移动表格全部数据
     * @param from 数据来源
     * @param to   数据最终要调价的地方
     */
    moveAllSelections(from: string, to: string) {
        // 需要移动的数据
        let moveData: any[];
        moveData = this[from + 'TableDataStorage'].filter(item => !item.isDisabled);
        // 新的数据
        const fromData = this[from + 'TableDataStorage'].filter(item => item.isDisabled);
        const toData: any[] = this[to + 'TableDataStorage'].concat(moveData);
        // 排序
        this.sortData(fromData);
        this.sortData(toData);

        this.$set(this, from + 'TableDataStorage', fromData);
        this.$set(this, to + 'TableDataStorage', toData);
        // 清除选中项
        (this.$refs[from + 'Table'] as any).clearSelection();
        (this.$refs[to + 'Table'] as any).clearSelection();
        this.selections[from] = [];
        this.selections[to] = [];
    }

    /**
     * 排序功能
     * @param data 要排序的数据
     */
    sortData(data: any[]): void {
        if (this.sort && typeof this.sort === 'string') {
            data.sort((a, b) => {
                if (a[this.sort as string] === b[this.sort as string]) {
                    return 0;
                }
                return a[this.sort as string] > b[this.sort as string] ? 1 : -1;
            });
        } else if (this.sort && typeof this.sort === 'function') {
            data.sort(this.sort);
        }
    }

    /**
     * 获取左边所有数据
     */
    getLeftAllData(): any[] {
        return this.leftTableDataStorage;
    }

    /**
     * 获取右边所有数据
     */
    getRightAllData(): any[] {
        return this.rightTableDataStorage;
    }

    /**
     * 初始化方法
     */
    initData(): void {
        // 初始化翻页数据
        this.searchData.left.data = '';
        this.searchData.left.temp = '';
        this.searchData.right.data = '';
        this.searchData.right.temp = '';

        // 初始化翻页数据
        this.page.left.currentPage = 1;
        this.page.right.currentPage = 1;

        // 初始化选中项
        if (this.$refs.leftTable) {
            (this.$refs.leftTable as any).clearSelection();
        }
        if (this.$refs.rightTable) {
            (this.$refs.rightTable as any).clearSelection();
        }
    }

    getSelectable(row) {
        if (this.isDisabled) {
            return !this.isDisabled;
        } else {
            if (row.isDisabled) {
                return false; // 禁止不可选择
            } else {
                // undefined或者false
                return true;
            }
        }
    }

    getDisabled(): boolean {
        return !this.isDisabled;
    }
}
</script>
<style lang="scss" scoped>
.trant {
    width: 700px;
    margin: auto;
    position: relative;

    .trant-left,
    .trant-right {
        width: 300px;
        height: 350px;

        .trant-content {
            border: 1px solid #eee;
            width: 300px;
            height: 330px;
            margin-top: 10px;

            .content-input {
                width: 290px;
                height: 40px;
                margin-top: 10px;
                background: #fff;
                padding-top: 4px;
                padding-left: 10px;
                position: relative;

                .left-p {
                    position: absolute;
                    right: 0;
                    top: 4px;

                    .el-icon-search {
                        color: #fff;
                    }
                }

                & /deep/ .el-button {
                    padding: 6px;
                }
            }
        }
    }

    .trant-but {
        position: absolute;
        top: 150px;
        left: 324px;

        .el-button {
            margin-top: 10px;
        }
    }

    .trant-right {
        position: absolute;
        top: 0;
        right: 0;
    }
}
</style>
